from flask import Blueprint, render_template, flash, url_for, request, redirect, send_file, Response, \
    stream_with_context, jsonify
from flask_login import current_user, login_required
from web.tools import authority_, queue_message, get_ip
from web.models import MovieData, User, EditUser, EditUserInfo, SpiderRunInfo
import os
import queue

admin_view = Blueprint('admin', __name__)


def delete_movie_img(path):
    """
    图片删除
    :param path: 图片路径
    :return: 图片删除状态（True：删除成功 / False：删除失败）
    """
    if os.path.exists(path):
        os.remove(path)
        return True
    else:
        return False


@admin_view.route('/')
@admin_view.route('/index')
@login_required
def index():
    page = request.args.get('page', 1, type=int)
    movie_data = MovieData.query.order_by(MovieData.score.desc()).paginate(page=page, per_page=10)
    return render_template('admin/index.html', movie_data=movie_data)


# 管理员电影数据管理列表
@admin_view.route('/movie-manage')
@login_required
@authority_(2)
def movie_manage():
    page = request.args.get('page', 1, type=int)
    movie_data = MovieData.query.order_by(MovieData.score.desc()).paginate(page=page, per_page=10)
    return render_template('admin/movie-manage.html', movie_manage=movie_data, url_endpoint=request.endpoint)

# 管理员电影数据管理搜索
@admin_view.route('/movie-manage/search')
@login_required
@authority_(2)
def movie_manage_search():
    page = request.args.get('page', 1, type=int)
    args = request.args.copy()
    args['page'] = str(page)
    if args.get('form-class') == "movie-title":
        movie_data = MovieData.query.filter(MovieData.title.contains(args.get('form-input'))).paginate(page=page,
                                                                                                       per_page=10)
    else:
        movie_data = MovieData.query.filter(MovieData.movie_type.contains(args.get('form-input'))).paginate(page=page,
                                                                                                            per_page=10)

    args_ = {}
    for key, value in args.items():
        if key != 'page':
            args_[key] = value

    return render_template('admin/movie-manage.html', movie_manage=movie_data, url_endpoint=request.endpoint,
                           args=args_)


# 管理员电影数据删除
@admin_view.route('/movie-manage/del')
@login_required
@authority_(2)
def movie_manage_del():
    movie_id = request.args.get('id')
    movie_data = MovieData.query.get(movie_id)
    if not movie_data:
        flash('数据删除失败', 'error')
        return redirect(url_for('admin.movie_manage'))
    movie_img = movie_data.img_url
    movie_data.delete()
    path = f"{os.path.abspath('.')}/web/static/{movie_img}"
    flash('数据删除成功', 'success')
    if delete_movie_img(path):
        flash('图片删除成功', 'success')
    else:
        flash('图片删除失败', 'error')
    return redirect(url_for('admin.movie_manage'))


# 管理员用户管理
@admin_view.route('/user-manage', methods=['GET', 'POST'])
@login_required
@authority_(2)
def user_manage():
    user_form = EditUser()
    page = request.args.get('page', 1, type=int)
    user_data = User.query.paginate(page=page, per_page=5)
    admin_count = User.query.filter_by(authority=2).count()
    return render_template('admin/user-manage.html', user_manage=user_data, admin_count=admin_count,
                           user_form=user_form)


# 管理员用户删除
@admin_view.route('/user-manage/del')
@login_required
@authority_(2)
def user_manage_del():
    user_id = request.args.get('user_id')
    user_data = User.query.get(user_id)
    if user_data:
        user_data.delete()
        flash('数据删除成功', 'success')
    else:
        flash('数据删除失败', 'error')
    return redirect(url_for('admin.user_manage'))


# 管理员用户修改
@admin_view.route('/user-manage/edit/<int:user_id>', methods=['POST'])
@login_required
@authority_(2)
def user_manage_edit(user_id):
    user_form = EditUser()
    if user_form.validate_on_submit():
        user_data = User.query.get(user_id)
        if user_data:
            user_data.username = user_form.username.data
            user_data.password = user_form.password.data
            user_data.authority = int(user_form.authority.data)
            user_data.authority_name = '管理员' if int(user_form.authority.data) == 2 else '普通用户'
            user_data.save()
            flash('数据修改成功', 'success')
        else:
            flash('数据修改失败', 'error')
    else:
        for field in user_form.errors.values():
            flash(field[0], 'error')
    return redirect(url_for('admin.user_manage'))


# 管理员用户添加
@admin_view.route('/user-manage/add', methods=['POST'])
@login_required
@authority_(2)
def user_manage_add():
    user_form = EditUser()
    if user_form.validate_on_submit():
        if User.query.filter_by(username=user_form.username.data).first():
            flash('当前用户名已存在', 'error')
            return redirect(url_for('admin.user_manage'))
        user_data = User()
        user_data.username = user_form.username.data
        user_data.password = user_form.password.data
        user_data.authority = int(user_form.authority.data)
        user_data.authority_name = '管理员' if int(user_form.authority.data) == 2 else '普通用户'
        user_data.save()
        flash('数据添加成功', 'success')
    else:
        for field in user_form.errors.values():
            flash(field[0], 'error')
    return redirect(url_for('admin.user_manage'))


# 个人信息
@admin_view.route('/user-info', methods=['POST', 'GET'])
@login_required
@authority_(1)
def user_info():
    edit_user_info = EditUserInfo()
    if request.method == 'POST':
        if edit_user_info.validate_on_submit():
            user_info_data = User.query.get(current_user.id)
            if user_info_data.check_password(edit_user_info.password_old.data):
                user_info_data.username = user_info_data.username
                user_info_data.password = edit_user_info.password.data
                user_info_data.save()
                flash('密码修改成功', 'success')
            else:
                flash('旧密码错误', 'error')
        else:
            for field in edit_user_info.errors.values():
                flash(field[0], 'error')
        return redirect(url_for('admin.user_info'))
    else:
        return render_template('admin/user-info.html', edit_user_info=edit_user_info)


# 爬虫代码
@admin_view.route('/spider-code', methods=['GET', 'POST'])
@login_required
@authority_(1)
def spider_code():
    if request.method == 'POST':
        return send_file('spider.py', mimetype='text/plain')
    else:
        return render_template('admin/spider-code.html')


@admin_view.route('/spider')
@login_required
@authority_(2)
def spider():
    movie_count = MovieData.query.count()
    spider_run_info = SpiderRunInfo.query.order_by(SpiderRunInfo.run_time.desc()).first()
    return render_template('admin/spider-run.html', movie_count=movie_count, spider_run_info=spider_run_info)


@admin_view.route('/spider-run')
@login_required
@authority_(2)
def spider_run():
    from datetime import datetime
    from web.spider import main
    from threading import Thread
    if MovieData.query.count() > 0:
        return jsonify({'code': 400, 'msg': '当前数据库中有数据，请先清空数据库'})
    else:
        spider_run_info = SpiderRunInfo()
        spider_run_info.run_time = datetime.now()
        spider_run_info.run_user = current_user.username
        spider_run_info.run_ip = get_ip()
        spider_run_info.save()
        spider_tasker = Thread(target=main)
        spider_tasker.start()
        return jsonify({'code': 200, 'msg': '爬虫开始运行'})


@admin_view.route('/spider-empty')
@login_required
@authority_(2)
def spider_empty():
    from web.setting import db
    MovieData.query.delete()
    db.session.commit()
    return jsonify({'code': 200, 'msg': '数据库清空成功'})


@admin_view.route('/stream')
@login_required
@authority_(2)
def spider_run_stream():
    def generate():
        while True:
            try:
                message = queue_message.get(block=True, timeout=1)
                if message == '任务完成':
                    yield f'data: {message}\n\n'
                    break
                yield f'data: {message}\n\n'
            except queue.Empty:
                continue

    return Response(stream_with_context(generate()), mimetype='text/event-stream')
